package com.chat.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chat.admin.Listener.ReadAdminExcelDataListener;
import com.chat.admin.domain.DTO.ADD.AddAdminDTO;
import com.chat.admin.domain.DTO.AdminDTO;
import com.chat.admin.domain.DTO.EDIT.EditAdminDTO;
import com.chat.admin.domain.VO.AdminVO;
import com.chat.admin.domain.pojo.AdminExcelEnter;
import com.chat.admin.mapper.AdminMapper;
import com.chat.admin.service.IAdminService;
import com.chat.admin.service.IRoleService;
import com.chat.admin.utils.RedisUtil;
import com.chat.common.common.constant.RedisKeyConstant;
import com.chat.common.common.exception.RoutineException;
import com.chat.common.entity.Admin;
import com.chat.common.entity.Authority;
import com.chat.common.entity.Role;
import com.chat.common.form.ListForm;
import com.chat.common.vo.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author weikjie
 * @since 2024-04-14
 */
@Service
@Slf4j
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements IAdminService {

    @Autowired
    IRoleService iRoleService;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public R<ListForm<AdminVO>> getAdminList(AdminDTO adminDTO) {
        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        //账号查询条件
        if(StringUtils.isNotBlank(adminDTO.getAccount())){
            queryWrapper.eq("account", adminDTO.getAccount());
        }
        //用户名查询
        if(StringUtils.isNotBlank(adminDTO.getUsername())){
            queryWrapper.eq("username", adminDTO.getUsername());
        }
        //角色查询条件
        if(StringUtils.isNotBlank(adminDTO.getRoleId())){
            queryWrapper.eq("role_id", adminDTO.getRoleId());
        }
        //状态查询
        if(adminDTO.getState()!=null){
            queryWrapper.eq("state", adminDTO.getState());
        }
        Page<Admin> adminPage = new Page<>(adminDTO.getPage(), adminDTO.getSize());
        IPage<Admin> adminList = page(adminPage, queryWrapper);
        List<AdminVO> adminListVO = convertToAdminVOList(adminList);
        //登录状态查询
        Boolean online = adminDTO.getOnLine();
        if (online != null) {
            if (online) {
                adminListVO = adminListVO.stream()
                        .filter(adminVO -> adminVO.getLoginTime() != null && !adminVO.getLoginTime().isEmpty())
                        .collect(Collectors.toList());
            } else {
                adminListVO = adminListVO.stream()
                        .filter(adminVO -> adminVO.getLoginTime() == null || adminVO.getLoginTime().isEmpty())
                        .collect(Collectors.toList());
            }
        }
        ListForm<AdminVO> adminListForm = new ListForm<>(adminDTO.getPage(),adminDTO.getSize(),
                adminList.getPages(), //总页数
                adminList.getTotal(), //总记录数
                adminListVO);
        return R.succeed(adminListForm);
    }

    @Override
    public R addOneAdmin(AddAdminDTO addAdminDTO) {
        if(!iRoleService.isRoleValid(addAdminDTO.getRoleId())){
            throw new RoutineException("当前角色已失效");
        }
        Admin admin = new Admin();
        BeanUtil.copyProperties(addAdminDTO, admin);
        admin.setPassword(passwordEncoder.encode(addAdminDTO.getPassword()));
        admin.setState(1);
        // 设置时间
        admin.setCreationTime(LocalDateTime.now());
        int insert = baseMapper.insert(admin);
        if (insert != 0){
            return R.succeed("添加成功");
        } else {
            return R.failed("添加失败");
        }
    }


    @Override
    public R<?> addExcelAdmin(MultipartFile file) {
        List<Role> roles = iRoleService.getStateRoles();
        Set<Long> validRolesIds = roles.stream()
                .map(Role::getId)
                .collect(Collectors.toSet());
        try {
            EasyExcel.read(file.getInputStream(), AdminExcelEnter.class, new ReadAdminExcelDataListener(this,validRolesIds)).sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("读取Excel文件时发生错误：{}", e.getMessage());
            return R.failed("读取Excel文件时发生错误");
        }
        return R.succeed("添加成功");
    }

    @Override
    public void convertToAdmins(List<AdminExcelEnter> adminExcels) {
        //System.out.println(adminExcels);
        List<Admin> adminList = adminExcels.stream().map(adminExcel -> {
            // 在这里将UserExcel转换为Admin
            Admin admin = new Admin();
            BeanUtil.copyProperties(adminExcel, admin);
            admin.setPassword(passwordEncoder.encode(adminExcel.getPassword()));
            admin.setState(1);
            // 设置时间
            admin.setCreationTime(LocalDateTime.now());
            return admin;
        }).toList();
        baseMapper.insertBatchSomeColumn(adminList);
    }

    //TODO:现在是清除token的方式
    @Override
    public R<?> DisableAccount(Long userID) {
        // 创建一个 UpdateWrapper 对象
        UpdateWrapper<Admin> updateWrapper = new UpdateWrapper<>();
        // 设置 id 等于 userID 的条件
        updateWrapper.eq("id", userID);
        // 设置 state 属性为 false
        updateWrapper.set("state", false);
        // 执行更新操作
        boolean result = update(updateWrapper);
        // 根据更新结果返回相应的响应
        if (result) {
            //清除token
            redisUtil.delete(RedisKeyConstant.ADMIN_ACCOUNT_ForToken + userID);
            return R.succeed("账号已成功禁用");
        } else {
            return R.failed("禁用账号失败");
        }
    }

    @Override
    public R<?> EnableAccount(Long userID) {
        // 创建一个 UpdateWrapper 对象
        UpdateWrapper<Admin> updateWrapper = new UpdateWrapper<>();
        // 设置 id 等于 userID 的条件
        updateWrapper.eq("id", userID);
        // 设置 state 属性为 false
        updateWrapper.set("state", true);
        // 执行更新操作
        boolean result = update(updateWrapper);
        // 根据更新结果返回相应的响应
        if (result) {
            return R.succeed("账号已成功启用");
        } else {
            return R.failed("启用账号失败");
        }
    }

    @Override
    public R<AdminVO> updateAdmin(EditAdminDTO editAdminDTO) {
        if(!iRoleService.isRoleValid(editAdminDTO.getRoleId())){
            throw new RoutineException("当前角色已失效");
        }
        Admin admin = new Admin();
        BeanUtils.copyProperties(editAdminDTO, admin);
        boolean result = updateById(admin);
        if(result){
            Admin updateAdmin = getById(editAdminDTO.getId());
            AdminVO updateAdminVO = convertToAdminVO(updateAdmin);
            return R.succeed("更新成功",updateAdminVO);
        }
        return R.failed("更新失败");
    }

    private List<AdminVO> convertToAdminVOList(IPage<Admin> userList) {
        return userList.getRecords().stream().map(this::convertToAdminVO).collect(Collectors.toList());
    }

    private AdminVO convertToAdminVO(Admin admin) {
        AdminVO adminVO = new AdminVO();
        //使用hutool工具包的映射可以转化1和0
        BeanUtil.copyProperties(admin, adminVO);
        //id太大会超越js的范围，换成string,Long和string不能直接映射需要转化
        adminVO.setId(admin.getId().toString());
        String time = (String) redisUtil.get(RedisKeyConstant.ADMIN_ACCOUNT_ForToken + admin.getId());
        if(time !=null && !time.isEmpty()){
            adminVO.setLoginTime(time);
        }
        return adminVO;
    }
}
